#include "image.h"


void Image::replaceFileName(const char *_fileName)
{
    if( fileName )
        delete [] fileName;
    fileName = new char[__strlen(_fileName)+1];
    __strcpy(fileName,_fileName);
}

void Image::loadImage()
{
    detachObject();
    allocObject(0);

    GFL_ERROR error;
    GFL_LOAD_PARAMS load_option;
    GFL_FILE_INFORMATION info;

    gflGetDefaultLoadParams(&load_option);
    load_option.LinePadding = 0;

	error = gflLoadBitmap(fileName, &data, &load_option, NULL);
	if(error) throw Exception(gflGetErrorString(error),EXCEPTION_INFOS);
    error = gflGetFileInformation(fileName,-1,&info);
	if(error) throw Exception(gflGetErrorString(error),EXCEPTION_INFOS);
}
// TODO (Administrateur#1#): trouver le nom du format a partir de l'extension!
void Image::saveImage()
{
    if( data == 0)
        throw Exception("Image is not defined",EXCEPTION_INFOS);

    GFL_ERROR error;
    GFL_SAVE_PARAMS save_option;
    char formatName[8];

    gflGetDefaultSaveParams( &save_option );
    setExtensionByName(formatName,fileName);

    save_option.Flags = GFL_SAVE_REPLACE_EXTENSION;
    save_option.FormatIndex = gflGetFormatIndexByName(formatName);
    save_option.Quality = 100;

    error = gflSaveBitmap(fileName, data, &save_option);
    if(error) throw Exception(gflGetErrorString(error),EXCEPTION_INFOS);

}



Image::Image() :
    AbstractSmartPointer<GFL_BITMAP,newGFL,delGFL,cpyGFL>() , fileName(new char[13])
{
    __strcpy(fileName,"untitled.jpg");
}

Image::~Image()
{
}

// TODO (Administrateur#1#): refaire constructeur par copie
Image::Image(const Image &image) :
    AbstractSmartPointer<GFL_BITMAP,newGFL,delGFL,cpyGFL>(image), fileName(new char[__strlen(image.fileName)+1])
{
    __strcpy(fileName,image.fileName);
}

// TODO (Administrateur#1#): refaire operateur =
Image& Image::operator=(const Image &image)
{
    this->AbstractSmartPointer<GFL_BITMAP,newGFL,delGFL,cpyGFL>::operator=(image);
    if( fileName )
        delete [] fileName;
    fileName = new char[__strlen(image.fileName)+1];
    __strcpy(fileName,image.fileName);

    return (*this);
}

Image::Image(const char * _fileName) :
    AbstractSmartPointer<GFL_BITMAP,newGFL,delGFL,cpyGFL>() , fileName(new char[__strlen(_fileName)+1])
{
    __strcpy(fileName,_fileName);   //copy string parameter in string attribute
    loadImage();
}


Image::Image(unsigned int width, unsigned int height) :
    AbstractSmartPointer<GFL_BITMAP,newGFL,delGFL,cpyGFL>(), fileName(new char[13])
{
    __strcpy(fileName,"untitled.jpg");
    GFL_COLOR color = { 0, 0, 0, 0 };
    data = gflAllockBitmap(GFL_RGB,width,height,3,&color);
}

Image::Image(unsigned int width, unsigned int height, unsigned char red, unsigned char green, unsigned char blue) :
    AbstractSmartPointer<GFL_BITMAP,newGFL,delGFL,cpyGFL>(), fileName(new char[13])
{
    __strcpy(fileName,"untitled.jpg");
    GFL_COLOR color = { red, green, blue, 0 };
    data = gflAllockBitmap(GFL_RGB,width,height,3,&color);
}

Image::Image(unsigned int width, unsigned int height, unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha) :
    AbstractSmartPointer<GFL_BITMAP,newGFL,delGFL,cpyGFL>(), fileName(new char[13])
{
    __strcpy(fileName,"untitled.jpg");
    GFL_COLOR color = { red, green, blue, alpha};
    data = gflAllockBitmap(GFL_ABGR,width,height,4    ,&color);
}


void Image::load()
{
    loadImage();
}

void Image::load(const char *_fileName)
{
    replaceFileName(_fileName);
    loadImage();
}

void Image::save()
{
    saveImage();
}

void Image::saveAs(const char *_fileName)
{
    replaceFileName(_fileName);
    saveImage();
}


void Image::resize(unsigned int width, unsigned int height)
{
    detachObject();

    replaceFileName("untitled.jpg");
    GFL_COLOR color = { 0, 0, 0, 0 };

    allocObject(0);
    data = gflAllockBitmap(GFL_RGB,width,height,3,&color);
}

void Image::resize(unsigned int width, unsigned int height, unsigned char red, unsigned char green, unsigned char blue)
{
    detachObject();

    replaceFileName("untitled.jpg");
    GFL_COLOR color = { red, green, blue, 0 };

    allocObject(0);
    data = gflAllockBitmap(GFL_RGB,width,height,3,&color);
}

void Image::resize(unsigned int width, unsigned int height, unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha)
{
    detachObject();

    replaceFileName("untitled.jpg");
    GFL_COLOR color = { red, green, blue, alpha};

    allocObject(0);
    data = gflAllockBitmap(GFL_ABGR,width,height,4    ,&color);
}


void Image::setChannels(unsigned int channels)
{
    unsharObject();
    GFL_ERROR error;
    GFL_MODE mode((channels==1)?GFL_MODE_TO_256GREY:GFL_MODE_TO_RGB);
    error = gflChangeColorDepth(data,NULL,mode,GFL_MODE_ADAPTIVE);
    if( error ) throw new Exception("Error when trying to change the type of the image",EXCEPTION_INFOS);
}

// TODO (Administrateur#1#): check sur bitmap avant acces
char *          Image::getFileName() const { return fileName; }
unsigned int    Image::getWidth()    const { return ((data)?data->Width:0); }
unsigned int    Image::getHeight()   const { return ((data)?data->Height:0);   }
unsigned int    Image::getChannels() const { return ((data)?data->BytesPerPixel:0); }
unsigned int    Image::getSize()     const { return ((data)?(data->Width*data->Height*data->BytesPerPixel):0);}


unsigned char * Image::getData()
{
    //std::cout<<"getData() "<<std::endl;
    unsharObject();
    return ((data)?data->Data:0);
}

unsigned char * Image::getData() const
{
    //std::cout<<"getData() const"<<std::endl;
    return ((data)?data->Data:0);
}

unsigned char * Image::getConstData() const
{
    //std::cout<<"getData() const"<<std::endl;
    return ((data)?data->Data:0);
}


double Image::getMean() const
{
    unsigned int size(getWidth()*getHeight()*getChannels()), n(0);
    double coef(1.0/(double)size), res(0.0);
    unsigned char * src(getConstData());

    for( n=0 ; n<size ; n++)
        res+= (*(src++))*coef;

    return res;
}

void Image::initImageLibrary()
{
    GFL_ERROR error;
    error = gflLibraryInit();
    if( error )
        throw Exception(gflGetErrorString(error),EXCEPTION_INFOS);
    //std::cout<< "  **  GLF V"<<gflGetVersion()<<" has been load   **  " <<std::endl;
}

void Image::freeImageLibrary()
{
    gflLibraryExit();
}

